from django.contrib.auth import PermissionDenied
from rest_framework import permissions
from django.utils.decorators import wraps
from django.conf import settings
from system.models import SysUserRole, SysRoleMenu
import logging

logger = logging.getLogger('ywadmin')


class IsAdminUser(permissions.BasePermission):
    """
    只允许管理员访问
    """
    def has_permission(self, request, view):
        return request.user and request.user.is_staff

class IsOwnerOrReadOnly(permissions.BasePermission):
    """
    允许所有者编辑，其他用户只读
    """
    def has_object_permission(self, request, view, obj):
        # 读取权限允许任何请求
        if request.method in permissions.SAFE_METHODS:
            return True
        
        # 写入权限只允许对象的所有者(需结合操作obj进行限制)
        return obj.owner == request.user

class IsOwnerOnly(permissions.BasePermission):
    """
    仅允许所有者编辑查看，防止水平越权
    """
    def has_object_permission(self, request, view, obj):
        # 写入权限只允许对象的所有者
        # 根据对象的不同属性判断所有权
        if hasattr(obj, 'user'):
            return obj.user == request.user
        elif hasattr(obj, 'owner'):
            return obj.owner == request.user
        # 对于用户对象本身，检查是否为当前用户
        elif hasattr(obj, 'id') and hasattr(request.user, 'id'):
            return obj.id == request.user.id
        return False


class MenuBasePermisson(permissions.BasePermission):
    def has_permission(self, request, view):
        # 超级管理员拥有所有权限
        # if request.user.is_superuser:
        #     return True

        # 未登录用户拒绝访问
        if not request.user.is_authenticated:
            return False

        current_path = request.path

        # 获取自定义排除路径
        exclude_paths = settings.MENU_PERM_EXCLUDE_PATHS
        if current_path in exclude_paths:
            return True

        # 获取用户角色
        user_roles = SysUserRole.objects.filter(user=request.user)
        user_roles = [role.role for role in user_roles]
        sys_role_menus = SysRoleMenu.objects.filter(role__in=user_roles)
        # logger.debug(f"用户[{request.user.username}]的角色菜单: {sys_role_menus}")
        has_perm_path = set()
        for menu in sys_role_menus:
            api_path = menu.menu.api_path
            if api_path:
                # 以,分割路由
                paths = api_path.split(',')
                for path in paths: 
                    has_perm_path.add(path)
        
        # logger.debug("has_perm_path[%s],current_path[%s]" % (has_perm_path,current_path))
        
        for path in has_perm_path:
            if current_path.startswith(path):
                return True
        return False


def has_role_permission(required_roles):
    """
    创建一个检查用户是否有特定角色的权限类
    使用方式：permission_classes = [has_role_permission(['admin'])]
    """
    class HasRole(permissions.BasePermission):
        def has_permission(self, request, view):
            if not request.user.is_authenticated:
                return False
                
            # 超级管理员始终有权限
            if request.user.is_superuser:
                return True
                
            # 获取用户角色
            user_roles = SysUserRole.objects.filter(user=request.user)
            user_role_codes = [role.role.code for role in user_roles]
            
            # 检查是否有所需角色
            for role in required_roles:
                if role in user_role_codes:
                    return True
            return False
    
    return HasRole

def has_role_permission_func(request, role_code):
    """
    创建一个检查用户是否有特定角色的权限类
    使用方式： 直接调用has_role_permission_func('admin')
    return:  True or False
    """
    user_roles = SysUserRole.objects.filter(user=request.user)
    user_role_codes = [role.role.code for role in user_roles]
    return role_code in user_role_codes


def has_role_permission_decorator(required_roles):
    def decorator(view_func):
        @wraps(view_func)
        def wrapper(request, *args, **kwargs):
            if not request.user.is_authenticated:
                return Response({'msg': '未登录'}, status=401)
            
            # 超级管理员始终有权限
            if request.user.is_superuser:
                return view_func(request, *args, **kwargs)
            
            # 获取用户角色
            user_roles = SysUserRole.objects.filter(user=request.user)
            user_role_codes = [role.role.code for role in user_roles]
            
            # 检查是否有所需角色
            for role in required_roles:
                if role in user_role_codes:
                    return view_func(request, *args, **kwargs)
            return Response({'msg': '无权限访问'}, status=403)
        return wrapper
    return decorator